package diseaseandcureadministration.registry;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.NoSuchElementException;

import diseaseandcureadministration.AbstractLoader;

/**
 * Registry is a fake abstract Singleton. Registries handles files
 * and a database and should be synchronized throughout the application
 * therefore the concrete subclasses are implemented as Singleton
 * Patterns
 * 
 * Most methods are implemented but getRegistryInstance must be
 * Overridden in subclasses (abstract static methods are not allowed)
 * 
 * @author Peter Tolstrup Aagesen, ptaa@itu.dk
 *
 */
public class Registry {
	
	private ArrayList<Registrable> _elements = new ArrayList<Registrable>();
	private AbstractLoader _loader;
	private boolean _isFileLoaded = false;
	
	protected Registry(){};

	public static synchronized Registry getRegistryInstance() {
		return null;
	}
	
	/**
	 * setLoader is a setter for loader variable
	 * 
	 * @param loader
	 */
	public void setLoader(AbstractLoader loader)
	{
		_loader = loader;
	}
	
	/**
	 * getElementByName return an element
	 * 
	 * @param name name of element, does not have to case sensitive
	 * @return element with the name
	 * @throws NoSuchElementException
	 */
	public Registrable getElementByName(String name) throws NoSuchElementException
	{
		Registrable foundElement = null;
		
		//Traverse elements 
		for(Registrable element: _elements)
		{
			//Check name
			if (element.getName().equalsIgnoreCase(name))
			{
				foundElement = element;
			}
		}	
		
		//If the element isn't in the registry throw 
		if(foundElement == null)
		{
			throw new NoSuchElementException("There is no element of that name in the registry");
		}
		
		return foundElement;
	}
	
	/**
	 * addElement adds an element to the Registry
	 * addElement ensures there are no duplicate elements
	 * in the Registry 
	 * 
	 * @param element 
	 */
	public void addElement(Registrable element)
	{
		//Check if the Symptom is in the registry already
		if(_elements.contains(element))
		{
			//Symptom found in registry
			return;
		}
		//Otherwise add the Symptom
		_elements.add(element);
		
		//Save symptoms
		save();		
	}
	
	/**
	 * getAll return all elements of the Registry
	 * 
	 * @return new ArrayList of all elements or at least an empty ArrayList
	 */
	public ArrayList<Registrable> getAll()
	{
		//Create variable for copying the elements
		ArrayList<Registrable> copiedElements = new ArrayList<Registrable>();
		
		//Copy all elements
		for(Registrable element: _elements)
		{
			copiedElements.add(element);
		}
		
		//Return list
		return copiedElements;
	}
	
	/**
	 * load() loads file into Registry
	 */
	public void load()
	{
		//Ensure the file isn't already loaded
		if(!_isFileLoaded)
		{
			try 
			{
				//Load file
				_elements = _loader.load();
			} 
			/*FileNotFoundExecption is a checked Exception but since the file is known 
			 *and shouldn't be moved it doesn't make sense to handle the exception;
			 *if the file is gone or broken the program should halt*/
			catch (FileNotFoundException e) 
			{
				throw new Error("The registry file is either deleted or removed");
			}
			_isFileLoaded = true;			
		}
	}
	
	public void save()
	{
		try 
		{
			//Save file
			_loader.save(_elements);
		} 
		/*FileNotFoundExecption is a checked Exception but since the file is known 
		 *and shouldn't be moved it doesn't make sense to handle the exception;
		 *if the file is gone or broken the program should halt*/
		catch (FileNotFoundException e) 
		{
			throw new Error("The registry file is either deleted or removed");
		}		
	}
}
